#include "sgu.h"

SGU_NS_BEGIN

const real AUREA = ((::sqrt(5.0) - 1.0)/2.0);        
const real COAUREA = ((-::sqrt(5.0) - 1.0)/2.0);
const real NaN = real_NaN();

real real_NaN()
{
	double x = std::numeric_limits<real>::signaling_NaN();
	ASSERT(!finite(x));
	return x;
}

real solve1G(const real a, const real b)         
{
	return -b/a;
}


std::pair<real,real> solve2G(const real a, const real b, const real c)
{
	const real delta = sqr(b)-4*a*c;
	if(delta<0) return std::make_pair(NaN,NaN); //only for optimization
	const real sqdelta = ::sqrt(delta);
	return std::make_pair((-b + sqdelta)/(2*a), (-b - sqdelta)/(2*a));
}



real round(const real x)
{
	return floor(x + 0.5);
}



real angle_0_2Pi(const real a)
{
	real x = fmod(a,2*M_PI);
	if (x<0) x+= (2*M_PI);
	return x;
}

real angle_Pi_Pi(const real a)
{                            
	real x = ::fmod(a,2*M_PI);
	if (x> M_PI) x-= (2*M_PI);
	if (x<-M_PI) x+= (2*M_PI);
	return x;
}



real stirling(real x)
{
	return ::pow(x,x) * ::exp(-x) * ::sqrt(2*M_PI*x);
}


natural factorial(natural x)
{
	natural p = 1;
	natural j;
	for(j=x;j>1;--j) p *= j;
	return p;
}



real fibonacciGen(real x)
{
	return 1/(::sqrt(5)*::pow(AUREA,x)) - 1/(::sqrt(5)*::pow(COAUREA,x));
}



natural fibonacci(natural x)
{
	if(x<=1) return x;

	natural a2 = 0;
	natural a1 = 1;
	natural p=0;

	natural j;
	for(j=1;j<x;j++)
	{
		p = a1+a2;
		a2 = a1;
		a1 = p;
	};
 
	return p;
}


void solveC2G(const Complex & a, const Complex & b, const Complex & c, Complex & x1, Complex & x2)
{
	Complex qdelta = std::sqrt(b*b - a*c*4.0);
	x1 = (-b + qdelta)/2.0;
	x2 = (-b - qdelta)/2.0;
}



SGU_NS_END
